package com.simplenix.nicasio.hmaint.servlet;

import com.simplenix.nicasio.hmaint.EntityDefinition;
import com.simplenix.nicasio.hmaint.EntityFactory;
import com.simplenix.nicasio.hmaint.util.HMaintUtil;
import com.simplenix.nicasio.misc.StrUtil;
import com.simplenix.nicasio.persistence.HibernateUtil;
import com.simplenix.nicasio.tags.Maint;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.hibernate.Criteria;
import org.hibernate.Transaction;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

/**
 *
 * @author fronald
 */
public class HMaintService extends HttpServlet {

	public static String ACTION_ADDUPDATE = "ADDUPDATE";

	public static String ACTION_VIEWUPDATE = "VIEWUPDATE";

	public static String ACTION_DELETE = "DELETE";

	public static String PARAM_ENTITY = "ENTITY";

	public static String PARAM_ACTION = "ACTION";

	public static String PARAM_PERPAGE = "PERPAGE";

	public static String ACTION_JSONDATA = "JSONDATA";

	public static String PARAM_BACK_TO = "BACK_TO";

	/**
	 * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
	 * @param request servlet request
	 * @param response servlet response
	 * @throws ServletException if a servlet-specific error occurs
	 * @throws IOException if an I/O error occurs
	 */
	protected void processRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();
		Transaction t = HibernateUtil.getCurrentSession().beginTransaction();
		Map<String, Object> params = new HashMap();
		for (Object key : request.getParameterMap().keySet()) {
			String k = (String) key;
			params.put(k, request.getParameter(k));
		}
		try {
			String action = StrUtil.nvl(request.getParameter(PARAM_ACTION));
			String entity = StrUtil.nvl(request.getParameter(PARAM_ENTITY));
			String backTo = StrUtil.nvl(request.getParameter(PARAM_BACK_TO));
			int page = StrUtil.string2Int(request.getParameter("page"));
			int rp = StrUtil.string2Int(request.getParameter("rp"));
			EntityDefinition ed = EntityFactory.getInstance().getEntityDefinition(entity);
			if (action.equals(ACTION_JSONDATA)) {

				String qType = StrUtil.nvl(request.getParameter("qtype"));
				String query = StrUtil.nvl(request.getParameter("query"));

				Criteria c = HMaintUtil.processRequest(request, entity);
				Criteria counter = HMaintUtil.processRequest(request, entity);

				if (!qType.equals("") && !query.equals("")) {
					c.add(Restrictions.like(qType, query, MatchMode.ANYWHERE));
					counter.add(Restrictions.like(qType, query, MatchMode.ANYWHERE));
				}

				int regs = (Integer) counter.setProjection(Projections.rowCount()).uniqueResult();
				c.setFirstResult((page * rp) - rp);
				c.setMaxResults(rp);
				List result = c.list();
				String jsom = "{";
				jsom += "\"page\": \"" + page + "\", \n";
				jsom += "\"total\": \"" + regs + "\", \n";
				jsom += "\"rows\": [ \n";
				for (Object r : result) {
					jsom += "{\"id\": \"" + HMaintUtil.getValue(r, ed.getKeyFieldName()) + "\", \"cell\": [";
					for (String field : ed.getFieldsNames()) {
						if (!ed.getFieldsHiddenOnList().contains(field)) {
							jsom += "\"" + HMaintUtil.getValue(r, field) + "\",";
						}
					}
					if (jsom.endsWith(",")) {
						jsom = jsom.substring(0, jsom.length() - 1);
					}
					jsom += "]},";
				}
				if (jsom.endsWith(",")) {
					jsom = jsom.substring(0, jsom.length() - 1);
				}
				jsom += " ] ";
				jsom += "}";
				out.write(jsom);
			} else if (action.equals(ACTION_ADDUPDATE)) {
				String key = ed.getKeyFieldName();
				if (params.containsKey(key)) {
					ed.getCustomUpdate().doUpdate(params, ed);
				} else {
					ed.getCustomAdd().doAdd(params, ed);
				}
				response.sendRedirect(backTo);
			} else if (action.equals(ACTION_DELETE)) {
				HMaintUtil.delete(params, Class.forName(entity));
				response.sendRedirect(backTo);
			} else if (action.equals(ACTION_VIEWUPDATE)) {
				Criteria criteria = HibernateUtil.getCurrentSession().createCriteria(entity);
				HMaintUtil.parseMapFindToCriteria(params, criteria, ed.getEntityClass());
				Object o = criteria.uniqueResult();
				String id = HMaintUtil.getValue(o, ed.getKeyFieldName());
				String rtn = Maint.surroundWithForm(ed.getCustomUpdate().getHtml(ed, id), ed, backTo);
				out.write(rtn);
			}
			t.commit();
		} catch (Exception ex) {
			t.rollback();
			out.write(ex.getLocalizedMessage() + "<br/><br/><a href='history.back(0);'>Back</a>");
		} finally {
			out.close();
		}
	}

	// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
	/**
	 * Handles the HTTP <code>GET</code> method.
	 * @param request servlet request
	 * @param response servlet response
	 * @throws ServletException if a servlet-specific error occurs
	 * @throws IOException if an I/O error occurs
	 */
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		processRequest(request, response);
	}

	/**
	 * Handles the HTTP <code>POST</code> method.
	 * @param request servlet request
	 * @param response servlet response
	 * @throws ServletException if a servlet-specific error occurs
	 * @throws IOException if an I/O error occurs
	 */
	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		processRequest(request, response);
	}

	/**
	 * Returns a short description of the servlet.
	 * @return a String containing servlet description
	 */
	@Override
	public String getServletInfo() {
		return "Short description";
	}// </editor-fold>

}
